const {
	isEmptyId,
	isNotEmptyId,
	isNotEmptyValue,
	isEmptyValue,
	isMobile,
	isLandLine,
	isIDCard,
	minLength,
	maxLength,
	isSafePassword,
	isNumber,
	isString,
	isENChar,
	isNull,
	isTrue,
	isFalse
} = require("./validatorStrategies")

/** 校验策略 */
const validatorStrategies = {
	"isEmptyId": isEmptyId,
	"isNotEmptyId": isNotEmptyId,
	"isNotEmpty": isNotEmptyValue,
	"isEmpty": isEmptyValue,
	"isMobile": isMobile,
	"isLandLine": isLandLine,
	"isIDCard": isIDCard,
	"minLength": minLength,
	"maxLength": maxLength,
	"isSafePassword": isSafePassword,
	"isNumber": isNumber,
	"isString": isString,
	"isENChar": isENChar,
	"isNull": isNull,
	"isTrue": isTrue,
	"isFalse": isFalse
}

/** =====================校验对象===================== */
let Validator = function() {
	this.cache = []; // 校验规则缓存
	this.validatorType = 'or'; // 整体校验规则： or 或（只有一个失败就抛出）| and 且（全部错误就抛出）
}

/**
 * 设置整体校验规则
 * @param {string} type // or 或（只有一个失败就抛出）and 且（全部错误就抛出）
 */
Validator.prototype.setValidatorType = function(type) {
	if (type != 'or' && type != 'and') {
		type = "or"
	}
	this.validatorType = type;
}

/**
 * 校验对象添加校验规则
 * @param {any} checkData 要检查的数据
 * @param {string} rule 校验规则---校验策略名 或者 校验策略名:校验限制参数（以：进行分割）
 * @param {string} errMsg 校验错误信息
 * @param {object} context 校验上下文，默认为null
 */
Validator.prototype.add = function(checkData, rule, errMsg, context = null) {
	let array = rule.split(":");
	this.cache.push(function() { // 使用空函数包装校验方法，并放入缓存
		var strategyKey = array.shift(); // 获取校验规则策略名称
		array.unshift(checkData); // 在首位插入要校验的数据
		if (errMsg) {
			array.push(errMsg) // 在末尾插入错误信息
		}
		return validatorStrategies[strategyKey].apply(context, array)
	})
}

/**
 * 触发校验
 */
Validator.prototype.start = function() {
	// 循环检验规则缓存
	let errMsgList = [];
	for (let i = 0; i < this.cache.length; i++) {
		let errMsg = this.cache[i](); // 开始执行缓存中的校验方法
		if (errMsg) { // 如果有返回值，校验没有通过， 抛出错误信息
			errMsgList.push(errMsg);
			if (this.validatorType == 'or') return errMsg;
		}
	}
	if (this.validatorType == 'and') {
		if (errMsgList && errMsgList.length == this.cache.length) { // 错误信息缓存长度 不等于 校验缓存长度， 有通过校验的内容
			return errMsgList[0];
		} else {
			return null;
		}
	}
	return null;
}

module.exports = Validator;